﻿using System;
using System.Diagnostics;
using Hallenberg.Core;
using Hallenberg.SmartClient.Interfaces;

namespace Hallenberg.SmartClient.Events
{
    /// <summary>
    /// The base class for all event handling classes. Derived classes implement
    /// their event handling code in 'OnEvent'. Derived classes fully implements
    /// dependency injection.
    /// </summary>
    /// <typeparam name="T">The type of value being passed to EventArgs</typeparam>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1012:AbstractTypesShouldNotHaveConstructors"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix", Justification = "The naming of this class is the most precise naming available")]
    public abstract class HandlesEvent<T> : IEventHandler
    {
        /// <summary>
        /// Handle the event raised in its simplest form. The EventArgs are then
        /// cast to the actual implementation 'EventArgs(T)' which are then passed
        /// to the type safe 'OnEvent' method that must be implemented in the derived class.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
        public void HandleEvent(object sender, EventArgs args)
        {
            Debug.Assert(sender != null);
            if (sender == null)
            {
                throw new ArgumentNullException("sender");
            }

            Debug.Assert(args != null);
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            OnEvent(sender, (EventArgs<T>)args);
        }

        public bool Async
        {
            get
            {
                return IsAsync();
            }
        }

        internal abstract void OnEvent(object sender, EventArgs<T> args);
        protected abstract bool IsAsync();
    }
}
